Previous Page TOC Next Page

38 — Unleashing LAN Programming

by Mark Steven Heyman

Shakespeare would have called it the dark backward and abysm of time—the dimly remembered, pre-Win95 days of yestermonth—when Visual Basic programmers who wanted to explore and manipulate the network resources underlying their applications were forced to link to the network provider's own Windows DLLs (Novell's NWNETAPI.DLL, for example), assuming these even were available. As you might imagine, this method of LAN resource management is at best tolerable—when a network consists of a single provider protocol. But in today's world, where it is not uncommon for a LAN (or WAN) to include two, three, or more distinct network protocols, this scheme becomes ponderous if not wholly unworkable.

With the introduction of Windows 95 and Windows NT, the creation and management of multi-protocol networks (as well as the creation of Windows applications to take full advantage of them) has been simplified greatly. A variety of network protocols and services can coexist under Windows 95 or NT, with no notion of primary or secondary networking software. Remote disk drives and printers can each be served by different network protocols—all under the watchful eye of the Win32 API. Under Windows 95, for example, drive E could be on a Windows NT server, drive G could be a NetWare server, and drive W could be a CD-ROM on a Sun Systems workstation across a WAN. The difference between local and network printers similarly has disappeared. The Win32 API offers the same basic programming interface for networking, regardless of the underlying software protocol and topology.

What this means to you, the Visual Basic programmer, is that your 32-Bit Visual Basic programs can call the network functions in the Microsoft Win32 application programming interface (API). These functions enable you to implement networking capabilities without making adjustments for a particular protocol provider or physical network configuration. In other words, the Win32 network functions are network independent. Your Visual Basic applications can use these functions to add and cancel network connections and to retrieve information about the current configuration of the physical network. In addition, the Win32 API implements a version of the NetBIOS network interface for applications that require it.


NOTE

In addition to using the network functions, your application's processes also can use the Win32 API implementations of mailslots and named pipes to communicate with one another. These topics will not be covered in this chapter, but for more information, see the discussions of mailslots and pipes in the online documentation for the Win32 SDK.

The Network Hierarchy

In this chapter, you'll be introduced to a dozen or so Win32 API functions (the Windows Network or WNet* functions) that can be called from your Visual Basic applications. (The asterisk in WNet* is a wild card character, indicating that all the function names begin with the same four letters.) But first, in order to familiarize yourself with the network jargon you'll encounter, take a look at Figure 38.1, which shows the structure of a typical multi-provider network.


FIGURE 38.1. A typical multi-provider network.

In Figure 38.1, the hierarchy for Microsoft Advanced Server resources is shown in detail as Network provider #2. Network resources from other providers (#1 might be Novell, for example, while #3 is Banyan) have different hierarchical systems. However, your Visual Basic application does not need information about the hierarchy before it begins to work with a network. It can proceed from the network root (that is, the topmost container resource) and retrieve information about the network's other resources as that information is required. Resources that do not contain other resources are regarded as objects. Sharepoint #1 and sharepoint #2 in Figure 38.1 are objects. A sharepoint is an object accessible across the network, such as a printer or shared directory.


NOTE

Network resources that contain other resources are called containers. An NT Advanced Server Domain is a container, as are any physical servers within it. In Figure 38.1, container resources are shown in boxes.

The Windows Network Functions

Windows 3.1 (and Windows For Workgroups) included the following protocol-independent network management functions (they did not, however, take advantage of 32-bit architecture):

The Win32 API supports these functions and has added the following network and network resource enumeration functions:

Your Visual Basic applications can use these network functions to browse, add, or cancel network connections anywhere in the hierarchy. By starting at the network root, the resources from all network providers can be listed for documentation or manipulation.

The Windows network functions enable your application to explore and manage network connections directly, or to give direct control of the network connections to your users. To call these functions, you must link to the multiple-provider router library (MPR.LIB). The following section discusses and demonstrates how to use many of these functions in your Visual Basic applications.

Function Declarations and the API Text Viewer

First, start a new Visual Basic project, add a new standard code module, and name it VBUCODE. Next, you'll add some function declarations to your new module with the help of the API Text Viewer. The API Text Viewer is a great little tool included with Visual Basic 4.0. You can use it to paste long and cumbersome function declarations, constants, and custom data types into your Visual Basic modules. The API Text Viewer is located in the Visual Basic 4.0 group. In fact, there may be two of them there: one for 16-bit development and one for 32-bit projects. In this chapter, you'll be working with the Win32 API. From the Viewer's File menu, select Load Text File and load Win32Api.Txt. This process takes a while, so be patient. There's a lot of stuff here.


CAUTION

After the API text file is first loaded, you may be asked if you want to convert the text file to a database for faster loading. In the beta copy of Visual Basic 4.0, answering Yes to this question caused the system to hang. The problem may well be fixed in your version of Visual Basic 4.0, but... well, you're on your own here.

After the file is loaded, select Declares from the API Type drop-down list. In the Available Items list, locate WNetAddConnection and double-click it to add it to the Selected Items list. Do the same for WNetCancelConnection. Your screen should look something like Figure 38.2.


FIGURE 38.2. The Win32 API Text Viewer.

After the functions are selected in the Selected Items list, click the Copy button to copy them to the Clipboard. Then switch to your VBUCODE module and paste them in. That's all there is to it. This way, you're ensured of getting an accurate declaration, no matter how long and cumbersome the statement. Just minimize the API Text Viewer for now—you'll need it again later.

The next step is to rename your project's default form (Form1) to something a little more descriptive—frmVBNet, for example. This form will provide an interface for connecting to, and disconnecting from, network resources.


NOTE

All the examples in this chapter were created using the 32-bit version of Visual Basic 4.0, on a Windows 95 computer in a peer-to-peer relationship with a Pentium system running Windows NT Workstation, Version 3.51.

Figure 38.3 shows how the Visual Basic IDE (Integrated Development Environment), including frmVBNet, will look once you've completed the form's visual implementation.


FIGURE 38.3. The Connecting to Network Resources dialog box.

Now complete the visual design of your new form, referring to Table 38.1 for significant objects and suggested settings.

Visual Basic Object


Property


Design Time Setting


Form

Name

Caption

frmVBNet

Connecting To Network Resources

TextBox

Name

txtNetPath

TextBox

Name

txtDrive

TextBox

Name

txtPassWord

Drive List Box

Name

Drive1

Command Button

Name

Caption

Default

cmdConnect

&Connect

True

Command Button

Name

Caption

cmdDisconnect

&Disconnect

Program Overview

As you probably have surmised, this form enables the user to connect to a network resource, such as a shared directory, by providing the resource's network path and an available drive letter. Because some network resources might be password protected, there's also a TextBox control for entering the password. The DriveList control will be used to verify a successful connection, as well as to select a current resource for disconnection.

You've already DECLARED the WNetAddConnection and WNetCancelConnection functions you'll need. Now it's time to take a closer look at these functions, and to put them into action.

The WNetAddConnection Function

This function enables your application to connect a local device to a network resource. A successful connection is always persistent, meaning that Windows automatically attempts to restore the connection at the next logon. Here's the syntax, followed by a discussion of the parameters and possible error conditions:

lngRetVal = WNetAddConnection(strRemoteName,strPassword,strLocalName)

Here, the strRemoteName parameter is a string variable that specifies the complete path to the desired network resource. The parameter strPassword specifies the password to be used to make a connection, if one is required. This parameter is usually the password associated with the current user. If the string is empty, no password is used. The last parameter, strLocalName, is a string variable that identifies the name of the local device to be redirected, such as F or LPT1. If this string is NULL, a connection to the network resource is made, but no local device is redirected.

If the connection is successful, the value returned by this function, lngRetVal, is equal to the value of the constant ERROR_SUCCESS (which can be located, along with any other constants mentioned in this chapter, under Constants in the API Text Viewer and pasted into your VBUCODE module).

If the function fails and no connection is made, the return value is an error code constant. Table 38.2 lists the most likely error codes for the WNetAddConnection function.

Constant


Meaning


ERROR_ACCESS_DENIED

Access is denied

ERROR_ALREADY_ASSIGNED

The device specified in the strLocalName parameter already is connected

ERROR_BAD_DEV_TYPE

The device type and the resource type do not match

ERROR_BAD_DEVICE

Value specified in strLocalName is invalid

ERROR_BAD_NET_NAME

Value specified in the strRemoteName parameter is not valid or cannot be located.

ERROR_BAD_PROFILE

User profile is in an incorrect format

ERROR_CANNOT_OPEN_PROFILE

System is unable to open the user profile to process persistent connections

ERROR_DEVICE_ALREADY_REMEMBERED

An entry for the device specified in strLocalName is already in the user profile

ERROR_EXTENDED_ERROR

A network-specific error occurred

ERROR_INVALID_PASSWORD

Specified password is invalid

ERROR_NO_NET_OR_BAD_PATH

Operation cannot be performed because either a network component is not started or the specified name cannot be used

ERROR_NO_NETWORK

No network is present

The WNetCancelConnection Function

This simple function breaks an existing network connection. Here's its syntax:

lngRetVal = WNetCancelConnection(strName,bForce)

Here, the parameter strName is a string variable containing the name of the redirected local device (F or LPT1, for example) or the network resource to be disconnected. When strName specifies a redirected local device, only the specified redirection is broken, and Windows will not restore the connection during ensuing logon operations. When this parameter specifies a remote network resource, the connection to that remote network resource is broken.

The bForce parameter is a Boolean value indicating whether the disconnection is to occur even if there are open files or uncompleted jobs on the connection. If this parameter is FALSE, the function fails if there are open files or jobs, and an appropriate error code is returned.

If the function succeeds, the return value, lngRetVal, is ERROR_SUCCESS. If the function fails, the return value may be an error listed in Table 38.2 or Table 38.3.

Constant


Meaning


ERROR_DEVICE_IN_USE

The specified device is in use by an active process and cannot be disconnected

ERROR_NOT_CONNECTED

The name specified by the strName parameter is not a redirected device, or the system is not currently connected to the device specified by the parameter

ERROR_OPEN_FILES

There are open files or uncompleted processes, and the bForce parameter is FALSE

Adding Code to Your Network Connection Form

It's time to add some spark to your new Network Connection form. The action occurs when cmdConnect or cmdDisconnect is clicked. Listings 38.1 and 38.2 are the documented listings for those two event procedures.

Private Sub cmdConnect_Click()

Dim ServerText As String, PassWordText As String     ' Useful variables

Dim DriveLetter As String

Dim Msg As String               ' For returned error message.

Dim Succeed As Long             ' For long value returned by functions.

ServerText = UCase$(txtNetPath) ' Network resource name

PassWordText = txtPassWord      ' Password for the resource

DriveLetter = txtDrive          ' Get drive letter

Succeed = WNetAddConnection(ServerText, PassWordText, DriveLetter)

If IsSuccess(Succeed, Msg) = True Then      ' Call custom function

                                            ' with returned value

                                            ' to test for success

                                            ' and/or get error message.

    Drive1.Refresh                          ' If successful connect,

                                            ' show new connection in

                                            ' drive list box.

Else                                        ' Function not successful

    MsgBox Msg, , "Visual Basic Unleashed!" ' so display error.

End If

End Sub

Listing 38.2 shows the code to be added to cmdDisconnect's Click event. Notice that you select the drive to be disconnected by picking it from the DriveList drop-down list.

Private Sub cmdDisconnect_Click()

Dim DriveLetter As String, Msg As String

Dim Succeed As Long

DriveLetter = Mid$(Drive1.Drive, 1, 2)              ' Get drive letter.

Succeed = WNetCancelConnection(DriveLetter, True)   ' Send it to the

                                                    ' CancelConnection

                                                    ' function, along

                                                    ' with a TRUE to

                                                    ' force the

                                                    ' disconnect, even

                                                    ' with open files

                                                    ' and/or processes.

If IsSuccess(Succeed, Msg) = True Then              ' If successful,

   Drive1.Refresh                                   ' refresh drive list

Else

   MsgBox Msg, , "Visual Basic Unleashed!"          ' Otherwise, display

                                                    ' the error message.

End If

End Sub

Listing 38.3 shows the IsSuccess() function, which is really just a specialized error handler. This code should be added to your VBUCODE module.

Function IsSuccess(ReturnCode As Long, Msg As String) As Boolean

If ReturnCode = ERROR_SUCCESS Then

   IsSuccess = True

Else

   IsSuccess = False

   Select Case ReturnCode

    Case ERROR_INVALID_FUNCTION:

       Msg = "Function is not supported."

    Case ERROR_OUTOFMEMORY:

       Msg = "Out of Memory."

    Case ERROR_BAD_NET_NAME:

       Msg = "Invalid Network Resource Name."

    Case ERROR_NO_RESOURCE_NAME:

       Msg = "Must Enter A Valid Network Resource Name."

    Case ERROR_INVALID_PASSWORD:

       Msg = "The Password was Invalid."

    Case ERROR_ACCESS_DENIED:

       Msg = "A Security Violation Occurred."

    Case ERROR_ALREADY_CONNECTED:

       Msg = "Local Device Already Connected."

    Case ERROR_CONNECTION_UNAVAIL:

       Msg = "The Resource Is Not Shared."

    Case ERROR_ALREADY_ASSIGNED:

       Msg = "Local Drive Identifier Is In Use."

    Case ERROR_BAD_USERNAME:

       Msg = "No Such User."

    Case ERROR_INVALID_PRINTER_NAME:

       Msg = "No Such Printer."

    Case ERROR_LOCAL_DRIVE:

       Msg = "Can't Disconnect Local Drive."

    Case ERROR_INTERNAL_ERROR:

       Msg = "Internal Error!"

    Case Else:

       Msg = "Unrecognized Error " + Str$(ReturnCode) + "."

  End Select

End If

End Function

Finally, you'll need to set up the ERROR constants referred to in the IsSuccess() function. Add the lines shown in Listing 38.4 to your VBUCODE module, using the API Text Viewer if you find it easier.

Public Const ERROR_SUCCESS = 0&

Public Const ERROR_INVALID_FUNCTION = 1&

Public Const ERROR_ACCESS_DENIED = 5&

Public Const ERROR_OUTOFMEMORY = 14&

Public Const ERROR_ALREADY_CONNECTED = 52&

Public Const ERROR_BAD_NETPATH = 53&

Public Const ERROR_UNSHARED_RESOURCE = 67&

Public Const ERROR_BAD_NET_NAME = 67&

Public Const ERROR_ALREADY_ASSIGNED = 85&

Public Const ERROR_INVALID_PASSWORD = 86&

Public Const ERROR_BUFFER_OVERFLOW = 111&

Public Const ERROR_BAD_PATHNAME = 161&

Public Const ERROR_ALREADY_EXISTS = 183&

Public Const ERROR_NO_RESOURCE_NAME = 487&

Public Const ERROR_CONNECTION_UNAVAIL = 1201&

Public Const ERROR_BAD_PROVIDER = 1204&

Public Const ERROR_BAD_PROFILE = 1206&

Public Const ERROR_EXTENDED_ERROR = 1208&

Public Const ERROR_INVALID_PASSWORDNAME = 1216&

Public Const ERROR_INTERNAL_ERROR = 1359&

Public Const ERROR_INVALID_PRINTER_NAME = 1801&

Public Const ERROR_BAD_USERNAME = 2202&

Public Const ERROR_LOCAL_DRIVE = 2250&

It's time to test your form, assuming that you're working in a network environment. Be sure frmVBNet is your project's StartUp form, and then run your program. Test your form by trying various connections and disconnections. If the functions are not successful, you should get an appropriate error message. If they are successful, you'll be able to drop down the DriveList box and verify the connection, or disconnection, as the case may be.

Figure 38.4 shows a sample session where the connection was successful.

In Figure 38.5, you see the results of an attempt to connect to an unshared directory.


FIGURE 38.4. The Network Connection form in action.


FIGURE 38.5. A failed connection attempt.

The WNetAddConnection2 Function

One of the disadvantages of plain ol' WNetAddConnection is that you have no control over the type of connection you make—that is, whether it's persistent. (Remember that a persistent connection is one that is "remembered" by Windows, and is automatically re-established at the next logon. Connections made with WNetAddConnection are persistent.)

Using WNetAddConnection2, you can specify a persistent connection or one that is valid only for the current session. The price you pay for this is a little more complexity in making the call. As you'll see in the following discussion, WNetAddConnection2 requires a custom data type, NETRESOURCE, as one of its parameters. You need to add the type definition and constants shown in Listing 38.5 to your VBUCODE module.

Type NETRESOURCE

    lngScope As Long           ' To specify scope during enumeration.

    lngType As Long            ' Defines the type of resource.

    lngDisplayType As Long     ' How resources will be displayed.

    lngUsage As Long           ' Specifies the resource usage.

    strLocalName As String     ' Local device for the connection.

    strRemoteName As String    ' Indicates the network resource.

    strComment As String       ' For a provider-supplied comment.

    strProvider As String      ' Name of provider who owns the resource.

End Type

Public Const RESOURCETYPE_ANY = &H0           ' These are some useful

Public Const RESOURCETYPE_DISK = &H1          ' constants to be used

Public Const RESOURCETYPE_PRINT = &H2         ' with many of the WNet

Public Const RESOURCETYPE_UNKNOWN = &HFFFF    ' functions.

Public Const CONNECT_UPDATE_PROFILE = &H1

Now here's the syntax for WNetAddConnection2, followed by a detailed discussion of all its parameters:

lngRetVal=WNetAddConnection2(nrCon,strPassword,strUserName,lngConnect)

The first parameter, nrCon, is a NETRESOURCE structure (in Visual Basic, a custom data type) that provides details of the proposed connection. It contains information about the network resource, the local device to be redirected, and the network resource provider. When calling WNetAddConnection2, you must specify the members of the NETRESOURCE data type shown in Table 38.4.

Member


Description


lngType

Specifies the type of network resource to connect to. If strLocalName points to a non-empty string, this member can be one of the constants RESOURCETYPE_DISK or RESOURCETYPE_PRINT. If strLocalName is NULL or empty, lngType can be RESOURCETYPE_DISK, RESOURCETYPE_PRINT, or RESOURCETYPE_ANY.

strLocalName

A string that specifies the name of a local device to be redirected, such as "X:" or "COM1". The case of the string is unimportant. If the string is empty or NULL, the function makes a connection but does not redirect the resource to a local device.

strRemoteName

A string that specifies the network resource to connect to. This string must adhere to the network provider's naming conventions.

strProvider

Specifies the network provider to connect to. If strProvider is NULL or empty, the operating system attempts to determine the correct provider by parsing the string pointed to by strRemoteName.

If this member is not NULL, the operating system attempts to make a connection only to the named network provider.

You should set this member only if you know for sure which network provider you want to use. Otherwise, let the operating system determine which provider the network name maps to.

The WNetAddConnection2 function ignores the other members of the NETRESOURCE structure.

The second parameter expected by WNetAddConnection2, strPassword, is a string that specifies a password to be used in making the network connection, if one is required. If this string is NULL, the function uses the current default password associated with the user specified by strUserName. If strPassword is an empty string, the function does not use a password.

The third parameter, strUsername, is a string that specifies a user name to be used in making the connection. If strUserName is NULL, the function uses the resource's default user name. The strUserName parameter is specified when users want to connect to a network resource for which they have been assigned a user name or account other than the default user name or account.

The final parameter, lngConnect, is used to specify connection options. When this parameter is set to CONNECT_UPDATE_PROFILE, the network resource connection is remembered, and Windows automatically attempts to restore the connection when the user logs on. If this parameter is 0, the user's profile is not updated and Windows will not automatically restore the connection at logon.

As with other WNet* functions, the return value, lngRetVal, is ERROR_SUCCESS if the function is successful in making the connection. If the function fails, the return value is an error code from one of the ERROR CODE tables in this chapter. Table 38.5 describes two additional errors associated with this function.

Constant


Meaning


ERROR_BUSY

The router or provider is busy, possibly congested or initializing. The function should be retried.

ERROR_CANCELLED

The connection attempt was canceled by the user through a dialog box from one of the network resource providers, or by a called resource or other process.

Finally, Listing 38.6 shows how your new form's cmdConnect Click event might look if you were using WNetAddConnection2 to connect to a network disk resource and make the connection persistent.

Private Sub cmdConnect_Click()

Dim ServerText As String, PassWordText As String

Dim DriveLetter As String, UserName As String

Dim Msg As String

Dim Succeed As Long

Dim nrConnect As NETRESOURCE                   ' Get NETRESOURCE var.

nrConnect.lngType = RESOURCETYPE_DISK          ' Set resource type.

nrConnect.strLocalName = txtDrive              ' Get drive letter.

nrConnect.strRemoteName = UCase$(txtNetPath)   ' Path to resource.

nrConnect.strProvider = ""                     ' Unknown provider.

PassWordText = txtPassword                     ' Get password.

UserName = ""                                  ' Default user.

Succeed = WNetAddConnection2(nrConnect, PassWordText, UserName, CONNECT_UPDATE_PROFILE)     ' Here's the call, all on one line.

                            ' Set the last parameter to 0, if you

                            ' don't want a persistent connection.

If IsSuccess(Succeed, Msg) = True Then

    Drive1.Refresh

Else

    MsgBox Msg, , "Visual Basic Unleashed!"

End If

End Sub

CAUTION

If you intend to test WNetAddConnection2 and WNetCancelConnection2 in your current project, be sure to use the API Text Viewer to add the function declarations to your VBUCODE module. Otherwise, the functions will not be known to Visual Basic.

The WNetCancelConnection2 Function

The WNetCancelConnection2 function is very similar to WNetCancelConnection, but has a little more punch. WNetCancelConnection2 requires three arguments. The first is the resource identifier; the second is either 0 or CONNECT_UPDATE_PROFILE; and the third indicates whether the connection should be broken if files are open or processes are uncompleted.

Listing 38.7 shows how you might use WNetCancelConnection2 to break a connection during the current session, and not have any effect on that connection's persistence (or lack of persistence) at the next logon.

Private Sub cmdDisconnect_Click()

Dim DriveLetter As String, Msg As String

Dim Succeed As Long

DriveLetter = Mid$(Drive1.Drive, 1, 2)  ' Get drive letter from list.

                                        ' You might want to get this

                                        ' from the txtDrive TextBox

                                        ' instead.

Succeed = WNetCancelConnection2(DriveLetter,0,False) ' Don't update the

                                                     ' user's connection

                                                     ' profile, and

                                                     ' don't force the

                                                     ' break if files

                                                     ' are open.

If IsSuccess(Succeed, Msg) = True Then

   Drive1.Refresh

Else

   MsgBox Msg, , "Visual Basic Unleashed!"

End If

End Sub

The WNetConnectionDialog Function

The WNetConnectionDialog function displays a general resource browsing dialog box. It's very useful if all you require is a simple, predefined interface for making network connections. WNetConnectionDialog saves you the hassle of having to design and implement your own dialog box. Listing 38.8 shows how it's used.

lngRetVal = WNetConnectionDialog(hWinHandle,lngResourceType)

The first parameter, hWinHandle, is a handle to the window which will own the dialog box. In Visual Basic, this is simply your calling form's hWnd property. The second parameter, lngResourceType, specifies which type of resource, or resources, to browse. The value of lngResourceType is one of the RESOURCETYPE constants: RESOURCETYPE_DISK or RESOURCETYPE_PRINT.

If the function succeeds, the return value, lngRetVal, is ERROR_SUCCESS. If the user cancels the dialog box, it is 0xFFFFFFFF, and no connection is made. As usual, the return value is an error code if the function fails.


NOTE

If the user chooses OK in the dialog box, the requested network connections are attempted. If the function attempts to make a connection and the network provider returns the message ERROR_INVALID_PASSWORD, Windows prompts the user to enter a password, which then is used to make another connection attempt.

The WNetDisconnectDialog Function

The WNetDisconnectDialog function displays a general browsing dialog box for breaking current network connections. The syntax and parameters are nearly identical to those of WNetConnectionDialog. Here's how the function is used:

lngRetVal = WNetDisconnectDialog(hWinHandle,lngResourceType)

You now should use the API Text Viewer to paste declarations for these two functions into your VBUCODE module. To test the Connect and Disconnect dialog functions, you'll add a simple form to your current project. Call it frmDialogs and make it the project's StartUp form. The form consists of two CommandButtons, and a Frame enclosing two OptionButtons, as displayed in Figure 38.6.


FIGURE 38.6. The Connections Dialog Boxes form.

Table 38.6 shows your new form's significant objects and property settings. Use it to complete the visual implementation of frmDialogs.

Visual Basic Object


Property


Design Time Setting


Form

Name

frmDialogs


Caption

Connection Dialog Boxes

Command Button

Name

cmdConnectDialog


Caption

Open &Connect Dialog

Command Button

Name

cmdDisconnectDialog


Caption

Open &Disconnect Dialog

Frame

Name

fraResources


Caption

Select Resource

OptionButton

Name

optDisk


Caption

Disk Resource


Value

True

OptionButton

Name

optPrinter


Caption

Printer Resource

By now, you probably have discerned the purpose of this form. It enables you to select a resource type, disk, or printer; and then open the corresponding Connect or Disconnect dialog box by clicking the appropriate CommandButton. Listing 38.9 shows the code for cmdConnectDialog's Click event.

Private Sub cmdConnectDialog_Click()

Dim Succeed As Long                                ' For return value.

Dim Resource As Long                               ' For resource type.

If optDisk Then                                    ' If optDisk is True,

   Resource = RESOURCETYPE_DISK                    ' use disk constant,

   Else                                            ' otherwise,

   Resource = RESOURCETYPE_PRINT                   ' use print constant.

End If

Succeed = WNetConnectionDialog(hWnd, Resource)     ' Here's the call.

                                                   ' Notice the use

                                                   ' of hWnd, the

                                                   ' calling window's

                                                   ' handle, which is

                                                   ' just frmDialogs'

                                                   ' hWnd property.

End Sub

Listing 38.10 shows cmdDisconnectDialog's nearly identical Click event procedure.

Private Sub cmdDisconnectDialog_Click()

Dim Succeed As Long

Dim Resource As Long

If optDisk Then

   Resource = RESOURCETYPE_DISK

   Else

   Resource = RESOURCETYPE_PRINT

End If

Succeed = WNetDisconnectDialog(hWnd, Resource)

End Sub

You're ready to test. Figures 38.7 and 38.8 show some sample sessions.


FIGURE 38.7. The Printer Connect dialog box in action.


FIGURE 38.8. The Disk Disconnect dialog box in action.

The WNetGetUser Function

The WNetGetUser function retrieves the current network user name, or the user name used to establish a current network connection. Here is WNetGetUser's syntax, followed by a discussion of all parameters:

lngRetVal =  WNetGetUser(strLocalName,strUserName,lngBuffer)

Here, strLocalName is a string that specifies the name of the local device to return the user name (for "LPT2" or "L:", for example), or the name of a network resource to which the user has made a connection. If strLocalName is NULL, Windows returns the name of the current user. If this parameter is a valid network resource and the user is connected to that resource using different names, the network provider might not be able to resolve which user name to return. In this case, the provider can choose arbitrarily from the possible user names.

The second parameter, strUserName, is a blank-space string variable that receives the user name. It must be big enough to contain the returned user name. The last parameter, lngBuffer, is a long variable that specifies the size, in characters, of the variable indicated by strUserName. If the call fails because the buffer is too small, the function returns a value equal to the error code constant ERROR_MORE_DATA, and lngBuffer contains the required buffer size.

Again, if the function succeeds, the value returned to lngRetVal is ERROR_SUCCESS. If the function fails, the return value is an error code that can be evaluated and subsequently displayed.

The WNetGetConnection Function

The WNetGetConnection function retrieves the name of the network resource currently associated with a particular local device. Here is how it's used:

lngRetVal =  WNetGetConnection(strLocalName,strRemoteName,lngBuffer)

The strLocalName parameter is a string variable that specifies the name of the local device whose network resource name is to be returned.

The second parameter, strRemoteName, is a blank space string variable that receives the remote resource name used to make the connection. The last parameter, lngBuffer, is a long variable that specifies the size, in characters, of the variable indicated by strRemoteName. If the function is not successful because the lngBuffer is too small, WNetGetConnection returns a value equal to the error code constant ERROR_MORE_DATA, and lngBuffer contains the required buffer size.

As with all the WNet* functions, if WNetGetConnection succeeds, the value returned to lngRetVal is ERROR_SUCCESS.

If the function fails, the return value is one of the previously discussed error codes, which you can capture and display.

Using WNetGetUser and WNetGetConnection

In this section, you'll put your understanding of the WNetGetUser and WNetGetConnection functions to use. First, add another form to your current project, call it frmNetInfo, and make it the project's StartUp form.

Now refer to Figure 38.9 and Table 38.7 to complete the visual design of your new form.


FIGURE 38.9. frmNetInfo in Design mode.

Visual Basic Object


Property


Design Time Setting


Form

Name

frmNetInfo


Caption

Network Information Form

TextBox

Name

txtDevice


TabIndex

0

Command Button

Name

cmdShowUser


Caption

Show &User


Default

True

Command Button

Name

cmdShowResource


Caption

Show &Resource

This form enables the user to enter a local device ID, such as LPT1: or Z:, and to receive the user name or network resource name associated with the device. (Don't forget to add the function declarations for WNetGetUser and WNetGetConnection to your VBUCODE module.) Listing 38.11 shows the code to add to the Click event procedures for cmdShowUser and cmdShowResource.

Private Sub cmdShowUser_Click()

Dim GetUser As Long                   ' For the return value.

Dim DeviceID As String                ' Local device.

Dim UserName As String                ' To receive user name.

Dim lngName As Long                   ' User name buffer size.

Dim Msg As String                     ' For MsgBox display.

UserName = Space(25)

lngName = Len(UserName)

DeviceID = txtDevice

GetName = WNetGetUser(DeviceID, UserName, lngName)  ' The call.

'Now prepare and display the user information.

Msg = "Device " + DeviceID + vbCrLf + "Is Being Used By " + UserName

MsgBox Msg, , "Network User Information"

End Sub

Listing 38.12 shows cmdShowResource's Click event.

Private Sub cmdShowResource_Click()

Dim GetResource As Long                   ' RetVal

Dim DeviceID As String                    ' Local device.

Dim ResourceName As String                ' For resource name.

Dim lngResource As Long                   ' Buffer size.

Dim Msg As String                         ' For MsgBox.

ResourceName = Space(50)

lngResource = Len(ResourceName)

DeviceID = txtDevice

GetResource = WNetGetConnection(DeviceID, ResourceName, lngResource)

'Now prepare and display the resource information.

Msg = "Device " + DeviceID + vbCrLf + "Connected To: " + ResourceName

MsgBox Msg, , "Network Resource Information"

End Sub

Okay, go ahead and test your form on your own network. See Figures 38.10 and 38.11 for sample output. Figure 38.11 shows some resource connection information, as displayed by the frmNetInfo program.


FIGURE 38.10. Network user information.


FIGURE 38.11. Network connection information.

The WNetGetLastError Function

The final function you'll cover in this chapter is the WNetGetLastError function. This function retrieves the most recent extended error code set by a Windows network function. An extended error code is network-specific; that is, it is supplied by a particular network provider—Novell or Banyan, for example—and therefore contains error information that pertains only to that provider's network protocol.

Here's the syntax for the WNetGetLastError function:

lngRetVal =  WNetGetLastError(lngCode,strDesc,lngDesc,strName,lngName)

The first parameter, lngCode, is a long variable that receives the network-specific error code reported by the provider software.

The next parameter, strDesc, receives the string describing the error. The parameter lngDesc specifies the size, in characters, of strDesc. If the variable is too small for the error string, the string is truncated. A variable of at least 256 characters is recommended.

The fourth parameter, strName, is a string variable that receives the name identifying the network provider that threw the error. The fifth and last parameter, lngName, sets the size, in characters, of the strName parameter.

If the function successfully obtains the last error reported by the network provider, the return value is ERROR_SUCCESS.

A Custom Extended Error Handler

WNetGetLastError should be used when any Windows network function returns ERROR_EXTENDED_ERROR. As mentioned earlier, this function returns detailed error information that is network specific, including a string for reporting errors that are not described by any existing Windows error code.

Now, in this final section, you'll enhance your IsSuccess() function, the simple error handler you created earlier in this chapter so that it can handle extended as well as standard error codes. In the process, you'll create a new custom function called ExErrorHandler. Listing 38.13 shows you what should be added to your VBUCODE module.

Function ExErrorHandler() As String

Dim strRetVal As String         ' For returned error message.

Dim ExRV As Long                ' For value returned by function.

Dim ExEC As Long                ' Stores the error code.

Dim ExED As String              ' Stores the error description.

Dim ExDS As Long                ' The size of description variable.

Dim ExPR As String              ' Stores the provider name.

Dim ExPS As Long                ' The size of the provider variable.

ExED = Space(256)               ' Initial values

ExDS = Len(ExED)

ExPR = Space(30)

ExPS = Len(ExPR)

ExRV = WNetGetLastError(ExEC, ExED, ExDS, ExPR, ExPS)  ' The call.

If ExRV = ERROR_SUCCESS Then    ' Check for success.

                                ' If successful, build network

                                ' specific error message to be

                                ' returned to IsSuccess function.

strRetVal = "Extended Error Information" + vbCrLf + vbCrLf

strRetVal = strRetVal + "Error Code: " + CStr(ExEC) + vbCrLf

strRetVal = strRetVal + "Error Description: " + ExED + vbCrLf

strRetVal = strRetVal + "Network Provider: " + ExPR

Else                                              ' Otherwise,

strRetVal = "Unable To Process Extended Error!"   ' Return generic msg.

End If

ExErrorHandler = strRetVal          ' Return message to IsSuccess()

End Function

Now your new function, ExErrorHandler(), is called from the IsSuccess() function you created near the beginning of this chapter. It is called only when one of your WNet* functions returns an ERROR_EXTENDED_ERROR value. Listing 38.14 shows the code for IsSuccess(), with the call to ExErrorHandler printed in bold.

Function IsSuccess(ReturnCode As Long, Msg As String) As Boolean

   If ReturnCode = ERROR_SUCCESS Then

      IsSuccess = True

   Else

      IsSuccess = False

      Select Case ReturnCode

         Case ERROR_INVALID_FUNCTION:

            Msg = "Function is not supported."

         Case ERROR_OUTOFMEMORY:

            Msg = "Out of Memory."

         Case ERROR_BAD_NET_NAME:

            Msg = "Invalid Network Resource Name."

         Case ERROR_NO_RESOURCE_NAME:

            Msg = "Must Enter A Valid Network Resource Name."

         Case ERROR_INVALID_PASSWORD:

            Msg = "The Password was Invalid."

         Case ERROR_ACCESS_DENIED:

            Msg = "A Security Violation Occurred."

         Case ERROR_ALREADY_CONNECTED:

            Msg = "Local Device Already Connected."

         Case ERROR_CONNECTION_UNAVAIL:

            Msg = "The Resource Is Not Shared."

         Case ERROR_ALREADY_ASSIGNED:

            Msg = "Local Drive Identifier Is In Use."

         Case ERROR_BAD_USERNAME:

            Msg = "No Such User."

         Case ERROR_INVALID_PRINTER_NAME:

            Msg = "No Such Printer."

         Case ERROR_LOCAL_DRIVE:

            Msg = "Can't Disconnect Local Drive."

         Case ERROR_INTERNAL_ERROR:

            Msg = "Internal Error!"

         Case ERROR_EXTENDED_ERROR:      ' If Extended error, call

            Msg = ExErrorHandler()       ' ExErrorHandler() for

                                         ' processing and building

                                         ' a network-specific error

                                         ' message.

         Case Else:

            Msg = "Unrecognized Error " + Str$(ReturnCode) + "."

       End Select

   End If

 End Function

If you intend to use some version of this function in your applications, don't forget to paste the WNetGetLastError declaration into a standard code module.

Summary

In this chapter, you learned that the introduction of Windows 95 and Visual Basic 4.0 has greatly simplified the creation of Windows applications that can take full advantage of the networks on which they run. Now your 32-bit Visual Basic programs can call the WNet* network functions in the Microsoft Win32 application programming interface (API). These functions enable you to explore and manage mixed-protocol networks without making adjustments for a particular network software or topology. The Win32 network functions therefore enable your Visual Basic applications to be network independent.

You were introduced to all 13 WNet* functions, and you spent some time exploring nine of them in detail. You created a form that enables you to connect and disconnect network resources using WNetAddConnection and WNetCancelConnection, and then you modified that form to use the more powerful WNetAddConnection2 and WNetCancelConnection2 functions. You used WNetConnectionDialog and WNetDisconnectDialog to display predefined dialog boxes for facilitating network connections and disconnections, and you created a Network Information form, using WNetGetUser and WNetGetConnection, which enabled you to retrieve and display network user and resource names. Finally, you used WNetGetLastError to create a custom extended error handler, which enables you to evaluate and display network-specific error information.

Previous Page TOC Next Page